use anyhow::Result;
use chrono::Local;
use csv::Writer;
use csv::WriterBuilder;
use serde::{Deserialize, Serialize};
use std::fs;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::BufWriter;
use std::path::Path;

use crate::mod_rfid::proctags::conver::TagInfo;

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CSVGW {
    pub enable: bool,
    pub detail: bool,
    pub path: String,
    pub volu: String,
}

impl CSVGW {
    fn get_writer(&self, name: String) -> Result<(Writer<BufWriter<File>>, bool)> {
        let path = Path::new(&self.path).join(&self.volu);
        fs::create_dir_all(path.clone())?;
        let path = path.join(name);
        let csv_exists = path.exists();
        let mut f_bulider = OpenOptions::new();
        let file = f_bulider.create(true).write(true).append(true).open(path)?;
        let mut csv_builder = WriterBuilder::new();
        let csv_builder = csv_builder.has_headers(false);
        let writer = csv_builder.from_writer(BufWriter::new(file));
        //BufWriter: 优化底层I/O操作的性能
        Ok((writer, csv_exists))
    }

    pub fn channel_init(&self, channel: usize) -> Result<Writer<BufWriter<File>>> {
        let time = Local::now().format("%Y_%m_%d_%H_%M");
        let name = format!("Channel[{}]_{}.csv", channel + 1, time);
        let (mut writer, flag) = self.get_writer(name)?;
        if !flag {
            writer.write_record(&["ID", "EPC", "TID", "State", "Detail"])?;
        }
        Ok(writer)
    }

    pub fn write(self, saver: &mut Writer<BufWriter<File>>, info: TagInfo, index: usize) {
        if self.enable {
            let record = TagRecord {
                id: index,
                epc: info.epc,
                tid: info.tid,
                state: info.state.to_string(),
                detail: if self.detail {
                    info.detail
                } else {
                    String::new()
                },
            };
            if let Ok(()) = saver.serialize(record) {};
        }
    }
}

#[derive(Serialize, Default)]
pub struct TagRecord {
    pub id: usize,
    pub epc: String,
    pub tid: String,
    pub state: String,
    pub detail: String,
}
